package com.sywb.chuangyebao.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;

import com.sywb.chuangyebao.R;
import com.sywb.chuangyebao.bean.QARichInfo;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 富文本输入框
 */
public class RichEditText extends EditText {

    private static final int DEFAULT_LINK_HIGHLIGHT_COLOR = Color.parseColor("#4D6898");// 默认链接高亮颜色

    // 定义正则表达式
    private static final String AT = "@[\u4e00-\u9fa5\\w]+\\s";// @人（末尾含空格）
    private static final String TOPIC = "#[\u4e00-\u9fa5\\w]+#";// ##话题
    private static final String SUPERURL = "(((http|https)://)|((?<!((http|https)://))www\\.))" + ".*?" + "(?=(&nbsp;|[\\u4e00-\\u9fa5]|\\s|　|<br />|$|[<>]))";
    // private static final String EMOJI = "\\[[\u4e00-\u9fa5\\w]+\\]";// 表情

    private static final String REGEX = "(" + AT + ")|(" + TOPIC + ")|(" + SUPERURL + ")";

    private int mLinkHighlightColor = DEFAULT_LINK_HIGHLIGHT_COLOR;// 链接高亮的颜色，默认蓝色

    private OnLinkClickListener mOnLinkClickListener;

    // private Pattern pattern;

    private List<ChatInfo> textList;
    private HashMap<Integer, Integer> richMap;
    private String lastContent = null;
    private int lastPosition = 0;

    public RichEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context, attrs);
    }

    public RichEditText(Context context) {
        super(context);
        initView(context, null);
    }

    private void initView(Context context, AttributeSet attrs) {
        // 要实现文字的点击效果，这里需要做特殊处理
        setMovementMethod(LinkMovementMethod.getInstance());

        // pattern = Pattern.compile(REGEX);

        if (attrs != null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RichView);
            // 设置链接高亮颜色
            int mLinkHighlightColor = typedArray.getColor(R.styleable.RichView_linkHighlightColor, DEFAULT_LINK_HIGHLIGHT_COLOR);
            if (mLinkHighlightColor != 0) {
                setLinkHighlightColor(mLinkHighlightColor);
            }
            typedArray.recycle();
        }

        textList = new ArrayList<>();
        richMap = new HashMap<>();

        addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
                // 原有的文本，从start开始的count个字符将会被一个新的长度为after的文本替换，注意这里是将被替换，还没有被替换
                // Logger.e("beforeTextChanged 被执行----> charSequence=" + charSequence + "----start=" + start + "----after=" + after + "----count" + count);
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                // 原有的文本s中，从start开始的count个字符替换长度为before的旧文本
                // Logger.e("onTextChanged 被执行---->charSequence=" + charSequence + "----start=" + start + "----before=" + before + "----count" + count);

                if (charSequence == null || charSequence.length() == 0) {
                    textList.clear();
                    richMap.clear();
                    return;
                }

                if (lastContent == null || !lastContent.equals(charSequence.toString())) {

                    boolean isIncludeRich = false;

                    if (before > 0) {//表示有删除
                        // Logger.e("textList.size():" + textList.size());
                        if (start < textList.size()) {
                            ChatInfo startChat = textList.get(start);
                            if (startChat != null && startChat.isRich) {
                                // Logger.e("startChat.richPosition:" + startChat.richPosition);
                                if (startChat.richPosition == 0) {
                                    //不动Start
                                } else {
                                    // Logger.e("startChat.richPosition:" + startChat.richPosition);
                                    start = start - startChat.richPosition;
                                    before = before + startChat.richPosition;
                                }
                            } else {
                                // Logger.e("startChat.isRich:false");
                            }
                        }

                        // Logger.e("start:" + start + " before:" + before);

                        if (start + before < textList.size()) {
                            ChatInfo endChat = textList.get(start + before);
                            if (endChat != null && endChat.isRich && endChat.richPosition > 0) {
                                before = before + endChat.richLenght - endChat.richPosition;
                            }
                        }

                        for (int i = 0; i < before; i++) {
                            if (textList.size() > start) {
                                ChatInfo chatInfo = textList.get(start);
                                if (chatInfo != null && chatInfo.isRich && !isIncludeRich) {
                                    isIncludeRich = true;
                                }
                                textList.remove(start);
                            }
                        }
                    }

                    if (count > 0) {
                        String addText = charSequence.toString().substring(start, start + count);
                        int postion = start;

                        if (addText != null && !addText.equals("")) {
                            if (textList == null) {
                                textList = new ArrayList<>();
                            }

                            if (textList.size() < postion) {
                                postion = textList.size();
                            }

                            for (int i = 0; i < addText.length(); i++) {
                                String chat = addText.substring(i, i + 1);
                                textList.add(postion + i, new ChatInfo(chat));
                            }
                        }

                        // Logger.e("addText:" + addText);
                        // stringToList(textList, start, addText);

                        refresh();
                    }

                    if (isIncludeRich) {
                        // Logger.e("isIncludeRich");
                        setRichText();
                    } else {
                        lastContent = charSequence.toString();
                        // Logger.e("lastContent:" + lastContent);
                    }
                    // Logger.e("textList:" + listToString(textList));
                }
                lastPosition = start + count;
            }

            @Override
            public void afterTextChanged(Editable s) {
                int textLenght = s.length();
                requestFocus();
                if (lastPosition < 0 || lastPosition > textLenght) {
                    setSelection(textLenght);
                } else {
                    setSelection(lastPosition);
                }

//                String content = s.toString();
//                if (TextUtils.isEmpty(content)) {
//                    return;
//                }
//                if (lastContent == null || !lastContent.equals(content)) {
//                    lastContent = content;
//                    int index = getSelectionEnd();
//                    setText(getWeiboContent(content));
//                    requestFocus();
//                    setSelection(index);
//                }
            }
        });

        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                // Logger.e("setOnClickListener:" + getSelectionStart());
                int selectionStart = getSelectionStart();
                if (getSelectionStart() >= 0 && selectionStart < textList.size()) {
                    ChatInfo chatInfo = textList.get(selectionStart);
                    if (chatInfo != null && chatInfo.isRich && chatInfo.richPosition > 0) {
                        requestFocus();
                        setSelection(selectionStart - chatInfo.richPosition);
                    }
                }
            }
        });

    }

    public List<ChatInfo> stringToList(List<ChatInfo> listText, int index, String newText) {
        if (newText == null || newText.equals("")) {
            return listText;
        }
        String chat = newText.substring(0, 1);
        // Logger.e("stringToList:" + chat);
        if (listText.size() < index) {
            index = listText.size();
        }
        listText.add(index, new ChatInfo(chat));
        if (newText.length() > 1) {
            newText = newText.substring(1);
            index += 1;
            return stringToList(listText, index, newText);
        }
        return listText;
    }

    public String listToString(List<ChatInfo> listText) {
        StringBuffer text = new StringBuffer();
        for (ChatInfo chat : listText) {
            text.append(chat.chat);
        }
        return text.toString();
    }

    public void insertRich(LinkedHashMap<Integer, String> userMap) {
        // Logger.e("insertRich");
        int selectionStart = getSelectionStart();
        int selectionEnd = getSelectionEnd();

        if (selectionStart != selectionEnd) {
            selectionStart = selectionEnd;
        }

        if (selectionStart < 0) {
            selectionStart = getText().length();
        }

        insertRich(selectionStart, userMap);
    }

    public void insertRich(int position, LinkedHashMap<Integer, String> userMap) {
        if (userMap == null || userMap.size() == 0) {
            return;
        }

        List<ChatInfo> chatInfos = new ArrayList<>();

        for (Map.Entry<Integer, String> entry : userMap.entrySet()) {
            int userUId = entry.getKey();
            String userName = entry.getValue();
            if (richMap.containsKey(userUId)) {
                continue;
            }
            for (int j = 0; j < userName.length(); j++) {
                String chat = userName.substring(j, j + 1);
                ChatInfo chatInfo = new ChatInfo(chat, userName.length(), j);
                chatInfo.name = userName;
                chatInfo.uid = userUId;
                chatInfos.add(chatInfo);

                // Logger.e("userName:" + chat);
            }
        }
        textList.addAll(position, chatInfos);

        setRichText();
    }

    public void deleteRich(LinkedHashMap<Integer, String> userMap) {
        if (userMap == null || userMap.size() == 0) {
            return;
        }

        Map<Integer, Integer> delMap = new TreeMap<>(new Comparator<Integer>() {
            public int compare(Integer key1, Integer key2) {
                return key2 - key1;
            }
        });

        for (Map.Entry<Integer, String> entry : userMap.entrySet()) {
            int userUid = entry.getKey();
            if (richMap.containsKey(userUid)) {
                int position = richMap.get(userUid);
                delMap.put(position, userUid);
            }
        }

        if (delMap.size() > 0) {
            for (Map.Entry<Integer, Integer> entry : delMap.entrySet()) {
                int position = entry.getKey();
                int uid = entry.getValue();
                ChatInfo chatInfo = textList.get(position);
                if (chatInfo.isRich && chatInfo.uid == uid) {
                    for (int i = 0; i < chatInfo.richLenght; i++) {
                        textList.remove(position);
                    }
                    richMap.remove(uid);
                }
            }
            setRichText();
        }
    }

    public void deleteNormalText(int selectStart, int count) {
        for (int i = 0; i < count; i++) {
            if (textList.get(selectStart).isRich) {
                continue;
            }
            textList.remove(selectStart);
            break;
        }
        setRichText();
    }


    public void deleteNormalLastOne() {
        if (textList != null && textList.size() > 0 && !textList.get(textList.size() - 1).isRich) {
            textList.remove(textList.size() - 1);
        }
        setRichText();
    }

    public List<QARichInfo> getAllRichInfo() {
        // LinkedHashMap<String, Integer> userMap
        if (richMap != null && richMap.size() > 0) {
            // Logger.e("getAllRichInfo.richMap:" + JSON.toJSONString(richMap));
            List<QARichInfo> richInfoList = new ArrayList<>();
            for (Map.Entry<Integer, Integer> entry : richMap.entrySet()) {
                int uid = entry.getKey();
                int position = entry.getValue();
                ChatInfo chatInfo = textList.get(position);
                if (chatInfo.isRich && chatInfo.uid == uid) {
                    QARichInfo qaRichInfo = new QARichInfo();
                    qaRichInfo.position = position;
                    qaRichInfo.uid = uid;
                    qaRichInfo.richName = chatInfo.name;
                    richInfoList.add(qaRichInfo);
                    // Logger.e(JSON.toJSONString(chatInfo));
                }
            }
            return richInfoList;
        }
        return null;
    }

    public void refresh() {
        richMap.clear();
        for (int i = 0; i < textList.size(); i++) {
            ChatInfo chatInfo = textList.get(i);
            if (chatInfo.isRich && chatInfo.richPosition == 0) {
                richMap.put(chatInfo.uid, i);
            }
        }
    }

    public void setRichText() {
        StringBuffer text = new StringBuffer();
        richMap.clear();
        for (int i = 0; i < textList.size(); i++) {
            ChatInfo chatInfo = textList.get(i);
            if (!chatInfo.isRich) {
                text.append(chatInfo.chat);
            } else {
                if (chatInfo.richPosition == 0) {
                    richMap.put(chatInfo.uid, text.length());
                    text.append(chatInfo.name);
                }
            }
        }
        // Logger.e("setRichText.richMap:" + JSON.toJSONString(richMap));
        lastContent = text.toString();
        // Logger.e("lastContent:" + lastContent);
        setText(lastContent);
    }

    public SpannableString getWeiboContent(CharSequence source) {
        SpannableString spannableString = new SpannableString(source);

        // 设置正则
        Pattern mPattern = Pattern.compile(REGEX);
        Matcher matcher = mPattern.matcher(spannableString);

        if (matcher.find()) {
            // 重置正则位置
            matcher.reset();
        }

        while (matcher.find()) {
            // 根据group的括号索引，可得出具体匹配哪个正则(0代表全部，1代表第一个括号)
            String at = matcher.group(1);
            String topic = matcher.group(2);
            String superurl = matcher.group(3);
            // String emoji = matcher.group(4);

            // 处理@符号
            if (at != null) {
                // 获取匹配位置
                int start = matcher.start(1);
                ChatInfo chatInfo = textList.get(start);
                if (chatInfo.isRich) {
                    int end = start + chatInfo.richLenght;
                    MyClickableSpan clickableSpan = new MyClickableSpan(chatInfo.uid) {

                        @Override
                        public void onClick(View v) {
                            if (mOnLinkClickListener != null) {
                                mOnLinkClickListener.onAtClick(this.data);
                            }
                        }
                    };
                    spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }

            // 处理话题##符号
            if (topic != null) {
                int start = matcher.start(2);
                ChatInfo chatInfo = textList.get(start);
                if (chatInfo.isRich) {
                    int end = start + chatInfo.richLenght;
                    MyClickableSpan clickableSpan = new MyClickableSpan(chatInfo.uid) {

                        @Override
                        public void onClick(View v) {
                            if (mOnLinkClickListener != null) {
                                mOnLinkClickListener.onTopicClick(this.data);
                            }
                        }
                    };
                    spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }

            // 处理url地址
            if (superurl != null) {
                int start = matcher.start(3);
                int end = start + superurl.length();
                MyClickableSpan clickableSpan = new MyClickableSpan(superurl) {

                    @Override
                    public void onClick(View v) {
                        if (mOnLinkClickListener != null) {
                            mOnLinkClickListener.onUrlClick(this.data);
                        }
                    }
                };
                spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }

            // if (emoji != null) {
            // int start = matcher.start(4);
            // int end = start + emoji.length();
            // MyClickableSpan clickableSpan = new MyClickableSpan() {

            // @Override
            // public void onClick(View v) {
            // if (mOnLinkClickListener != null) {
            // mOnLinkClickListener.onEmojiClick(emoji);
            // }
            // }
            // };
            // int ResId = EmotionUtils.getImgByName(emoji);
            // Bitmap bitmap =
            // BitmapFactory.decodeResource(context.getResources(), ResId);
            // if (bitmap != null) {
            // // 获取字符的大小
            // int size = (int) textView.getTextSize();
            // // 压缩Bitmap
            // bitmap = Bitmap.createScaledBitmap(bitmap, size, size, true);
            // // 设置表情
            // ImageSpan imageSpan = new ImageSpan(context, bitmap);
            // spannableString.setSpan(imageSpan, start, end,
            // Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            // }
            // spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            // }
        }

        return spannableString;
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(getWeiboContent(text), type);
    }

    public void setLinkHighlightColor(int mLinkHighlightColor) {
        this.mLinkHighlightColor = mLinkHighlightColor;
    }

    public int getLinkHightlightColor() {
        return this.mLinkHighlightColor;
    }

    /**
     * 继承ClickableSpan复写updateDrawState方法，自定义所需样式
     */
    private class MyClickableSpan extends ClickableSpan {

        public Object data;

        MyClickableSpan(Object data) {
            this.data = data;
        }

        @Override
        public void onClick(View v) {
        }

        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setColor(mLinkHighlightColor);
            ds.setUnderlineText(false);
        }
    }

    public OnLinkClickListener getOnLinkClickListener() {
        return mOnLinkClickListener;
    }

    public void setOnLinkClickListener(OnLinkClickListener mOnLinkClickListener) {
        this.mOnLinkClickListener = mOnLinkClickListener;
    }

    /**
     * 链接点击的监听器
     */
    public interface OnLinkClickListener {
        /**
         * 点击了@的人， 如"@bining "
         */
        void onAtClick(Object userId);

        /**
         * 点击了话题，如"#中国#"
         */
        void onTopicClick(Object topicId);

        /**
         * 点击了url，如"http://www.google.com"
         */
        void onUrlClick(Object url);

        /**
         * 点击了表情
         */
        void onEmojiClick(String emoji);
    }

    public class ChatInfo {

        ChatInfo(String chat) {
            this.chat = chat;
            this.isRich = false;
            this.richLenght = 0;
            this.richPosition = 0;
        }

        ChatInfo(String chat, int richLenght, int richPosition) {
            this.chat = chat;
            this.isRich = true;
            this.richLenght = richLenght;
            this.richPosition = richPosition;
        }

        public String chat;
        public boolean isRich;
        public int richLenght;
        public int richPosition;
        public int uid;
        public String name;
    }

}
